/*********************************************
 *TCPServer for ESP8266.
 *Author: openthings@163.com. 
 *copyright&GPL V2.
 *Last modified 2014-10-20.
 **********************************************/

#include "ets_sys.h"
#include "os_type.h"
#include "osapi.h"
#include "mem.h"
#include "user_interface.h"

#include "version.h"

#include "espconn.h"
#include "user_json.h"
#include "driver/uart.h"

//#if ESP_PLATFORM
#include "xnet_base.h"
//#endif

#include "../xflow/xc_cmd.h"
#include "wix_tcpserver.h"

extern cmd_functionType cmd_fun[xc_cmdNum];
extern void xc_flow_onWifiReceiving(char* strwifi);	//接收到WiFi传来的数据。

//连接句柄，全局共享。
struct espconn esp_conn_server;
//static 
uint16_t server_timeover = 180;
uint16_t server_port = 8268;
/******************************************************************************
 * 按照缺省的端口启动TCP服务器。
*******************************************************************************/
void ICACHE_FLASH_ATTR	 tcpserver_start()
{
	tcpserver_init(server_port);
}

/******************************************************************************
 * FunctionName : user_webserver_init
 * Description  : parameter initialize as a server
 * Parameters   : port -- server port
 * Returns      : none 
*******************************************************************************/
void ICACHE_FLASH_ATTR	 tcpserver_init(uint32 port)
{
    LOCAL esp_tcp esptcp;

	//设置服务器超时参数。
	server_timeover = 3600;
	espconn_regist_time(&esp_conn_server, server_timeover, 0);

    esp_conn_server.type = ESPCONN_TCP;
    esp_conn_server.state = ESPCONN_NONE;
    esp_conn_server.proto.tcp = &esptcp;
    esp_conn_server.proto.tcp->local_port = port;
    espconn_regist_connectcb(&esp_conn_server, tcpserver_listen);

//#ifdef SERVER_SSL_ENABLE
//    espconn_secure_accept(&esp_conn_server);
//#else
    espconn_accept(&esp_conn_server);
//#endif
}

/******************************************************************************
 * FunctionName : user_accept_listen
 * Description  : server listened a connection successfully
 * Parameters   : arg -- Additional argument to pass to the callback function
 * Returns      : none
*******************************************************************************/
void ICACHE_FLASH_ATTR	
tcpserver_listen(void *arg)
{
    struct espconn *pesp_conn = arg;

    espconn_regist_recvcb(pesp_conn, tcpserver_recv);
    espconn_regist_reconcb(pesp_conn, tcpserver_recon);
    espconn_regist_disconcb(pesp_conn, tcpserver_discon);
}

/******************************************************************************
 * FunctionName : tcpserver_recv
 * Description  : Processing the received data from the server
 * Parameters   : arg -- Additional argument to pass to the callback function
 *                pusrdata -- The received data (or NULL when the connection has been closed!)
 *                length -- The length of received data
 * Returns      : none
*******************************************************************************/
void ICACHE_FLASH_ATTR
tcpserver_recv(void *arg, char *pusrdata, unsigned short length)
{
	pusrdata[length] = '\0';
	xc_flow_onWifiReceiving(pusrdata);
}

/******************************************************************************
 * FunctionName : tcpserver_send
 * 发送数据到WiFi端口，比如从串口来的数据实现透传。
 * Description  : Send data to wifi channel.
 * Parameters   : arg -- Additional argument to pass to the callback function
 *                pusrdata -- The received data (or NULL when the connection has been closed!)
 *                length -- The length of received data
 * Returns      : none
*******************************************************************************/
void ICACHE_FLASH_ATTR	
tcpserver_send(char *pbuf, unsigned short length)
{
	//struct espconn *pesp_conn = arg;

//#ifdef SERVER_SSL_ENABLE
//        espconn_secure_sent(&esp_conn_server, pbuf, length);
//#else
	espconn_sent(&esp_conn_server, pbuf, length);
//#endif
}

/******************************************************************************
 * FunctionName : webserver_recon
 * Description  : the connection has been err, reconnection
 * Parameters   : arg -- Additional argument to pass to the callback function
 * Returns      : none
*******************************************************************************/
ICACHE_FLASH_ATTR	void
tcpserver_recon(void *arg, sint8 err)
{
    struct espconn *pesp_conn = arg;

    os_printf("webserver's %d.%d.%d.%d:%d err %d reconnect\n", pesp_conn->proto.tcp->remote_ip[0],
    		pesp_conn->proto.tcp->remote_ip[1],pesp_conn->proto.tcp->remote_ip[2],
    		pesp_conn->proto.tcp->remote_ip[3],pesp_conn->proto.tcp->remote_port, err);
}

/******************************************************************************
 * FunctionName : tcpserver_recon
 * Description  : the connection has been err, reconnection
 * Parameters   : arg -- Additional argument to pass to the callback function
 * Returns      : none
*******************************************************************************/
ICACHE_FLASH_ATTR	void 
tcpserver_discon(void *arg)
{
    struct espconn *pesp_conn = arg;

    os_printf("Tcpserver's %d.%d.%d.%d:%d disconnect\n", pesp_conn->proto.tcp->remote_ip[0],
        		pesp_conn->proto.tcp->remote_ip[1],pesp_conn->proto.tcp->remote_ip[2],
        		pesp_conn->proto.tcp->remote_ip[3],pesp_conn->proto.tcp->remote_port);
}

/*******************************************************
 * 查询TCP/IP服务器信息。
  ******************************************************/
uint16_t get_tcpserver(void)
{
	return server_port;
}

void ICACHE_FLASH_ATTR xc_cmd_CIPSERVERQ(uint8_t id, char *pParam)
{
	char temp[32];
	os_sprintf(temp, "%s:%d\r", cmd_fun[id].cmdName, server_port);
	sendInfoAll(temp);		
}

/*******************************************************
 * 启动TCP/IP服务器。
  ******************************************************/
void ICACHE_FLASH_ATTR xc_cmd_CIPSERVER(uint8_t id, char *pParam)
{
	uint16_t ipPort;	
	ipPort = atoi(pParam);
	if (ipPort<=0)	{			
		tcpserver_start();			//按缺省端口启动服务器。
	} else {
		server_port = ipPort;
		tcpserver_init(ipPort);
	}
}

/*******************************************************
 * 关闭TCP/IP服务器。
  ******************************************************/
void ICACHE_FLASH_ATTR xc_cmd_CIPSCLOSE(uint8_t id, char *pParam)
{
		tcpserver_discon(NULL);
		sendInfoAll("TCPServer close.");
}

